#include"comm.hpp"

// 用于保护共享内存的数据
void Accept()
{
    bool ret = createFifo(NAMED_PIPE); // 创建管道
    assert(ret);

    int fd = open(NAMED_PIPE, O_RDONLY);
    if(fd < 0)
    {
        perror("server open error");
        exit(1);
    }
    char buffer[1024];
    while(1) // 不断的读取，判断client是否向管道内发送数据
    {
        ssize_t s = read(fd, buffer, sizeof(buffer)-1); // 读不到会阻塞
        if(s > 0)
        {
            //读取成功
            buffer[s] = '\0';
            cout << "client -> server: " << buffer << endl;
        }
        else if(s == 0)
        {
            // 管道已经关闭
            cout << "client quit\n";
            break;
        }
        else
        {
            perror("read error");
            exit(1);
        }
    }

    close(fd);
    removeFifo(NAMED_PIPE); // 删除管道文件
}

// 进程间通信，该进程负责接收clinet进程通过共享内存的通信信息
int main()
{
    // 创建key
    key_t k = getKey();
    //printf("0x%x\n", k); // 查看k的值，验证两个进程生成的key是否一样

    // 创建共享内存
    int shmid = CreateShm(k);
    cout << "shmid: " << shmid << endl;

    // 将共享内存链接到进程地址空间上
    char* start = (char*)attachShm(shmid);

    //通信
    // 如果想对共享内存的数据进行保护，可以使用命名管道
    // 这里server端作为读端向命名管道读取数据，如果没收到client端发来的数据就不对共享内存进行读取
    // 然后client如果不写完向共享内存中发送的数据就不会给管道发送数据。
    // 这样可以实现一个client不写完，server端阻塞的效果
    Accept();

    // 正式读取client发送的数据
    int time = 3;
    while(time--)
    {
        printf("client say: %s\n", start);
        sleep(1);
        
    }

    //将共享内存和进程地址空间去关联
    detachShm(start);

    //sleep(5); // 休眠5秒再删除, 为了能更好的观察到共享内存的状态
    DelShm(shmid); // 删除共享内存


    return 0;
}